(function(win){
	/*用于新建一个验证对象的构造函数，同时设定验证成功与失败时的动作，并设置遇到失败时是否继续验证，之后只需要用.check方法输入验证相关信息即可。
		fail_handler：验证未通过时执行的函数，不填时默认使用alert，函数会接受2个参数，分别是提示文本和表单项id
		pass_handler：验证通过时执行的函数，不填时默认什么都不执行，若有函数则会接受2个参数，分别是提示文本和表单项id
		check_all：布尔值，是一次验证全部表单并全都执行函数，还是遇到无法通过的就结束验证，不填时默认为fasle
			
				例：
				var verify_obj = new Verify(alert);//遇到验证失败就停止继续验证并弹出警告框显示错误原因
				
				var verify_obj = new Verify(
					function(text, id){//遇到验证失败就显示表单项所对应的提示文本
						$("#"+id+"_hint").show().html(text);
					},
					function(text, id){//验证成功的则隐藏表单项所对应的提示文本
						$("#"+id+"_hint").hide();
					},
					true//一次性验证每个表单项的值并根据验证结果执行相应的动作
				);
	*/
	var Verify = function(fail_handler, pass_handler, check_all){
		this.fail_handler = (typeof fail_handler === "function") ? fail_handler : null;
		this.pass_handler = (typeof pass_handler === "function") ? pass_handler : null;
		this.check_all = !!check_all;
	};
	if(!win.Verify){
		win.Verify = Verify;
	}else{
		alert("全局变量Verify已存在，请修改上面语句\"win.Verify\"的构造函数名！");
		return;
	}

	//私有变量
	var _obj, _id, _fail_text, _pass_text,
		_reg = {
			'姓名':/(^[\u4e00-\u9fa5]{2,7}$)|(^[a-zA-Z ·]{2,30}$)/,
			'邮箱':/^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/,
			'邮箱账户':/^([a-zA-Z0-9_\.\-])+$/,
			'手机':/^(1[2-8][0-9])\d{8}$/,
			'座机':/^([0-9]{3,4}-?)?[0-9]{7,8}$/,
			'身份证':/(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/,
			'IP地址':/^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/,
			'QQ号':/^[1-9][0-9]{4,}$/,
			'汉字':/^[\u4e00-\u9fa5]+$/,
			'字母':/^[A-Za-z]+$/,
			'有理数':/^(\-|\+)?(([1-9][0-9]*)|([0-9]+\.[0-9]+)|0)$/,
			'数字':/^[0-9]+$/,
			'数字或下划线':/^[0-9_]+$/,
			'字母或下划线':/^[A-Za-z_]+$/,
			'数字或字母':/^[A-Za-z0-9]+$/,
			'数字或字母或下划线':/^[A-Za-z0-9_]+$/,
			'非空':/[^ 　]/,
			'没有特殊字符':new RegExp("^[^`｀~～!！@＠#＃$＄%％^＾&＆*＊(（)）+＋=＝|｜{｛}｝'＇\"＂:：;；,，\\[［\\]］\\\\＼\.．<＜>＞/／?？￥……—\\-－_＿【】《》‘’“”。、·~　\\n\\r\\t]+$"),
			'不全是特殊字符':new RegExp("[^`｀~～!！@＠#＃$＄%％^＾&＆*＊(（)）+＋=＝|｜{｛}｝'＇\"＂:：;；,，\\[［\\]］\\\\＼\.．<＜>＞/／?？￥……—\\-－_＿【】《》‘’“”。、·~ 　\\n\\r\\t]")//比上个多半角空格
		};

	//私有函数
	/*
	function _trim(text){//过滤首尾空格
		return (text||"").replace(/^\s+|\s+$/g, "");
	}
	*/
	function _handler(condition, fail_text, pass_text){//执行验证通过或失败的函数
		var fail_handler = _obj.fail_handler,//脱离作用域执行函数
			pass_handler = _obj.pass_handler;
		if(condition){
			pass_handler && pass_handler(_pass_text || (pass_text || "输入格式正确"), _id);
			return true;
		}else{
			fail_handler && fail_handler(_fail_text || (fail_text || "输入格式错误"), _id);
			return false;
		}
	}
	function _checkOne(value, check_info){//根据验证需要进行不同验证
		var type, arg = 10,
			match = _obj.match;
		_fail_text = "";
		_pass_text = "";
		if(typeof check_info === "string"){
			type = check_info;
		}else if(typeof check_info === "object" && check_info.type){
			type = check_info.type;
			arg = check_info.arg;
			_fail_text = check_info.fail;
			_pass_text = check_info.pass;
		}else{
			alert("为id为"+_id+"的元素配置的验证设置的格式不正确。");
			return false;
		}
		if((type==="长于" || type==="短于" || type==="大于" || type==="小于" || type==="大于等于" || type==="小于等于" 
			|| type==="相同" || type==="正则" || type==="自定义") && typeof arg === "undefined"){
			alert("对id为“"+_id+"”的input元素所设置的“"+type+"”验证还需要输入参数“"+arg+"”。");
			return false;
		}
		switch(type){
			case '姓名':
				return _handler(match(value,"姓名"), "必须是长度合理的汉字或英文");
			case '手机或邮箱':
				return _handler((match(value,"手机") || match(value,"邮箱")));
			case '邮箱':
				return _handler(match(value,"邮箱"), "邮箱输入有误", "邮箱正确");
			case '邮箱账户':
				return _handler(match(value,"邮箱账户"), "邮箱输入有误", "邮箱正确");
			case '电话':
				return _handler((match(value,"手机") || match(value,"座机")), "电话号码输入有误", "电话号码正确");
			case '手机':
				return _handler(match(value,"手机"), "手机号码输入有误", "手机号码正确");
			case '座机':
				return _handler(match(value,"座机"), "座机号码输入有误", "座机号码正确");
			case '身份证':
				return _handler(match(value,"身份证"), "身份证号码输入有误", "身份证号码格式正确");
			case 'IP地址':
				return _handler(match(value,"IP地址"), "输入的IP地址格式有误", "IP地址格式正确");
			case 'QQ号':
				return _handler(match(value,"QQ号"), "输入的QQ号格式有误", "QQ号格式正确");
			case '汉字':
				return _handler(match(value,"汉字"), "必须输入汉字");
			case '字母':
				return _handler(match(value,"字母"), "必须输入字母");
			case '有理数':
				return _handler(match(value,"有理数"), "必须输入为正或为负的整数或小数");
			case '数字':
				return _handler(match(value,"数字"), "必须输入数字");
			case '数字或下划线':
				return _handler(match(value,"数字或下划线"), "必须输入数字或下划线");
			case '字母或下划线':
				return _handler(match(value,"字母或下划线"), "必须输入字母或下划线");
			case '数字或字母':
				return _handler(match(value,"数字或字母"), "必须输入数字或字母");
			case '数字或字母或下划线':
				return _handler(match(value,"数字或字母或下划线"), "必须输入数字或字母或下划线");
			case '非空':
				return _handler(match(value,"非空") && (value !== "" && value !== null && typeof value !== "undefined"), "必填项尚未填写", "已填写");
			case '没有特殊字符':
				return _handler(match(value,"没有特殊字符"), "不能输入任何特殊符号", "输入有效");
			case '不全是特殊字符':
				return _handler(match(value,"不全是特殊字符"), "必须输入有效的信息", "输入有效");
			case '正则':
				return _handler(match(value, "正则", arg));
			case '不短于':
				return _handler(((value+"").length >= arg), "至少要有"+arg+"个字符", "长度符合要求");
			case '不长于':
				return _handler(((value+"").length <= arg), "不能超过"+arg+"个字符", "长度符合要求");
			case '大于':
				return _handler((value.length > 0 ? (value*1 > arg) : false), "数字必须大于"+arg, "数字大小符合要求");
			case '小于':
				return _handler((value.length > 0 ? (value*1 < arg) : false), "数字必须小于"+arg, "数字大小符合要求");
			case '大于等于':
				return _handler((value.length > 0 ? (value*1 >= arg) : false), "数字必须大于等于"+arg, "数字大小符合要求");
			case '小于等于':
				return _handler((value.length > 0 ? (value*1 <= arg) : false), "数字必须小于等于"+arg, "数字大小符合要求");
			case '相同':
				return _handler((value == arg), "输入不一致", "输入正确");//不能使用全等
			case '不同':
				return _handler((value != arg), "输入不能是“"+arg+"”", "输入正确");//不能使用全等
			case '自定义':
				if(typeof arg !== "function"){
					alert("为id为"+_id+"的元素配置的“自定义”验证的参数必须是一个有返回值的函数。");
					return false;
				}
				return _handler(!!arg(value));
			default:
				alert("id为“"+_id+"”的input元素的验证类型“"+type+"”不存在。");
				return false;
		}
	}
	
	//可以不通过check方法直接使用，检查字符串的值是否匹配某种正则表达式，只有type为“正则”时参数reg才有用
	Verify.prototype.match = function(str, type, reg){
		if(type === "正则"){
			try{
				return (new RegExp(reg)).test(str);
			}catch(e){
				alert("正则表达式“"+reg+"”不正确。");
				return false;
			}
		}else if(_reg[type]){
			return _reg[type].test(str);
		}else{
			alert("验证类型“"+type+"”不存在。");
			return false;
		}
	};
	
	/*
		检查表单的值或元素的innerHTML
			参数必填，格式为表单项的id和验证方式的名值对对象，id对应的值是表示验证方式的字符串
				id所对应的值也可以是对象字面量，格式为 {type:验证方式, fail:错误文本, pass:正确文本, arg:相关参数}，仅type为必填
				可以对同一个id的表单项做出多个不同验证，用数组包含多个验证即可，无论是字符串还是对象
				若某些验证需要相关值却没有输入，会在浏览器控制台显示warn信息作为提醒
	
			例：
				verify_obj.check({
					'login_mobile':'手机',
					'login_password':{"type":"长度", "fail":"密码必须大于6位", "arg":6},
					'login_password_2':[
						"非空",
						{"type":"相同", "arg":$("#login_password").val()}
					]
				});
	*/
	Verify.prototype.check = function(input_data){
		if(!input_data){
			return true;
		}else if(typeof input_data === "string"){
			var data = {};
			data[input_data] = arguments[1];
			input_data = data;
		}else if(typeof input_data !== "object"){
			alert("方法check的参数不正确。");
			return false;
		}
		var ele, value, check_info,
			self = this,
			result = true,
			start = 0,
			fn;
		_obj = self;
		for(var id in input_data){
			if(!input_data.hasOwnProperty(id)) continue;
			if(!id || !input_data[id]) continue;
			check_info = input_data[id];
			_id = id;
			ele = document.getElementById(id);
			if(!ele) continue;
			value = ele.value || ele.innerHTML;
			if(typeof check_info === "object" && check_info instanceof Array){
				if(check_info[0] === "可空"){
					if(!value && value !== 0){//符合“可空”条件，仅执行空文本的成功函数
						fn = self.pass_handler;
						fn && fn("", id);
						continue;
					}else{
						start = 1;
					}
				}else{
					start = 0;
				}
				for(var i=start,len=check_info.length; i<len; i++){
					if(!_checkOne(value, check_info[i])){
						if(self.check_all){
							result = false;
							break;
						}else{
							return false;
						}
					}
				}
			}else if(!_checkOne(value, check_info)){
				if(self.check_all){
					result = false;
				}else{
					return false;
				}
			}
		}
		return result;
	}
})(window);